package com.zhq.blog.manage.domain.controller.support;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.zhq.blog.core.domain.Session;
import com.zhq.blog.core.domain.admin.AdminControllerDescription;
import com.zhq.blog.core.domain.admin.Operator;
import com.zhq.blog.core.domain.admin.WorkLog;
import com.zhq.blog.core.domain.support.EnumAwareConvertUtilsBean;
import com.zhq.blog.manage.domain.controller.BaseController;
import com.zhq.blog.manage.domain.controller.BossModel;

public class PermissionInterceptor extends HandlerInterceptorAdapter {
	protected Log logger = LogFactory.getLog(this.getClass());
	
	public static final String ADMIN_SESSION_ID_FLAG = "hualala_session_id";
	public static final String ADMIN_LOGIN_URL = "/admin/login/";
	public static final String ADMIN_LOGIN_VALID_URL = "/admin/login/valid";
	public static final int ADMIN_SESSION_TIMEOUT = 60*5;
	
	@Autowired
	private Session sessionService;

	
	@Override
	public boolean preHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler) throws Exception {
		BeanUtilsBean.setInstance(new BeanUtilsBean(new EnumAwareConvertUtilsBean()));
		//前台preHandle
		if((handler instanceof HandlerMethod && ((HandlerMethod)handler).getBean() instanceof BaseController ) || handler instanceof BaseController){
			String sessionId = getSessionId(request,response);
			Session session = sessionService.getOrCreateSession(sessionId);
			if(request.getRequestURI().endsWith(ADMIN_LOGIN_URL) || request.getRequestURI().endsWith(ADMIN_LOGIN_VALID_URL)){
				if(sessionId == null){
					setCookie(response,sessionService.getOrCreateSession(null).getId());
				}
				try{
					if(handler instanceof HandlerMethod){
						HandlerMethod method = (HandlerMethod)handler;
						setValue(method.getBean(),session,null);
					}
				}catch(Exception e){
					logger.debug("set session error",e);
				}
			}else{
				if(sessionId == null){
					response.sendRedirect(ADMIN_LOGIN_URL);
					return false;
				}
				Operator currentOperator = session.getOperator(request);
				if(currentOperator == null){
					response.sendRedirect(ADMIN_LOGIN_URL);
					return false;
				}else{
					if(handler instanceof HandlerMethod){
						HandlerMethod method = (HandlerMethod)handler;
						setValue(method.getBean(),session,currentOperator);
					}else if (handler instanceof BaseController){
						setValue(handler,session,currentOperator);
					}
				}
				checkPermission(currentOperator);			
			}
		
		}
		return true;
	}
	
	
	
	
	@Override
	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		//后台操作记录
		if(request.getRequestURI().startsWith("/admin")){
			Operator operator = null;
			BaseController controller = null;
			if(handler instanceof HandlerMethod){
				HandlerMethod method = (HandlerMethod)handler;
				if(method.getBean() instanceof BaseController){
					controller = (BaseController)method.getBean();
				}
				
			}else if (handler instanceof BaseController){
				controller = (BaseController)handler;
				operator = controller.getOperator();
			}
			if(controller != null && controller.getOperator() != null)operator = controller.getOperator();
			String operatorName =  (operator == null ? "无记录" : operator.getName());
			long operatorId = (operator == null ? 0 : operator.getId());
			String ip = request.getRemoteAddr();
			String url = request.getRequestURI();
			String method = request.getMethod();
			String content = "";
			if(modelAndView != null){
				Object descObj =modelAndView.getModel().getOrDefault(BossModel.CONTROLLER_DESCRIPTION_FLAG,null);
				if(descObj != null &&  descObj instanceof AdminControllerDescription){
					AdminControllerDescription desc = (AdminControllerDescription)descObj;
					content += desc.getCategory().getName() + " ";
				}
				content += "\t";
				content += modelAndView.getModel().getOrDefault(BossModel.ACTION_DESCRIPTION_FLAG, "");
			}
			new WorkLog().log(operatorName, operatorId, ip, content,url,method);
		}else{//前台操作记录
			
		}
		super.postHandle(request, response, handler, modelAndView);
	}




	private void setValue(Object _controller,Session session,Operator currentOperator){
		if(_controller instanceof BaseController){
			BaseController controller = (BaseController)_controller;
			controller.setSession(session);
			controller.setOperator(currentOperator);
		}
	}

	/**
	 * 返回session id，如果第一次访问或异常访问则返回null
	 * @param request HttpServletRequest
	 * @return  返回session id，如果第一次访问或异常访问则返回null
	 */
	private String getSessionId(HttpServletRequest request, HttpServletResponse response){
		String sessionId = null;
		
		Cookie[] cookies =  request.getCookies();
		if(cookies != null){
			for(Cookie cookie : cookies){
				if(cookie.getName().equals(ADMIN_SESSION_ID_FLAG) ){
					sessionId = cookie.getValue();
					setCookie(response,sessionId);
				}
			}
		}
		return sessionId;
	}

	/**
	 * 设置用户会话cookie
	 * TODO: 这里存在一个问题，用户可以自行修改cookie过期时间。不过由于cookie机制的安全性，一般认为不是大问题。作为未来改进点。
	 * @param response
	 * @param sessionId
	 */
	private void setCookie(HttpServletResponse response,String sessionId){
		Cookie cookie = new Cookie(ADMIN_SESSION_ID_FLAG,sessionId);
		cookie.setPath("/");
		cookie.setMaxAge(ADMIN_SESSION_TIMEOUT);
		response.addCookie(cookie);
	}
	
	private void checkPermission(Operator currentOperator){
		
	}
}